#pragma once
#include <iostream>
#include <cstdio>
#include <string>
#include <time.h>
#include<stdarg.h>
#include<unistd.h>
#include<fcntl.h>
#define INFO 1
#define WARING 2
#define ERR 3
#define FATAL 4
#define DEBUG 5
#define DISPLAY 1
#define ONEFILE 2
#define CLASSFILE 3
#define FILEPATH "./log/log"
class Log
{
public:
    Log()
    {
        _printMode = DISPLAY;
    }
    void setPrintMode(int mode)
    {
        _printMode = mode;
    }
   std::string getLeval(int leval)
    {
        switch (leval)
        {
        case INFO:
            return "INFO";
        case WARING:
            return "WARING";
        case ERR:
            return "ERR";
        case FATAL:
            return "FATAL";
        case DEBUG:
        return "DEBUG";
        }
    }
    void logMessage(int leval, const char *format, ...)
    {
        char leftformat[1024];
        time_t t = time(nullptr);
        struct tm *_time = localtime(&t);
        snprintf(leftformat,sizeof(leftformat),"[%s][%d - %d - %d  %d: %d: %d]",
         getLeval(leval).c_str(),_time->tm_year+1900,_time->tm_mon+1,_time->tm_mday,_time->tm_hour,_time->tm_min,_time->tm_sec);
        va_list s;
        va_start(s,format);
        char right[1024];
        vsnprintf(right,sizeof(right),format,s);
        va_end(s);
        char ch[2048];
        snprintf(ch,sizeof(ch),"%s %s\n",leftformat,right);
        // std::cout<<ch<<std::endl;
        Display(leval,ch);
    }
    void Display(int leval,const std::string &s)
    {
        if(_printMode == DISPLAY)
        {
            std::cout<<s<<std::endl;
        }
        else if(_printMode == ONEFILE)
        {
            int fd = open(FILEPATH,O_WRONLY|O_CREAT|O_APPEND,0666);
            write(fd,s.c_str(),s.size());
        }
        else 
        {
            std::string path(FILEPATH);
            path+="."+ getLeval(leval);
            int fd = open(path.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);
            write(fd,s.c_str(),s.size());
        }
    }

private:
    int _printMode;
};